package com.zpz.framework.zpzoauth.config.oauth.authorization.exouath.authenticator.sms;

import com.alibaba.fastjson.JSON;
import com.zpz.framework.zpzoauth.common.utils.ZpzOauthMsgUtils;
import com.zpz.framework.zpzoauth.common.utils.ZpzOauthCommonConstant;
import com.zpz.framework.zpzoauth.common.result.ZpzOauthResultMsg;
import com.zpz.framework.zpzoauth.common.result.ZpzOauthResultStatus;
import com.zpz.framework.zpzoauth.common.utils.ZpzOauthRequestUtil;
import com.zpz.framework.zpzoauth.dao.FrameDepartmentMapper;
import com.zpz.framework.zpzoauth.pojo.pe.GetDepartmentStatusPe;
import com.zpz.framework.zpzoauth.pojo.po.OauthClientDetails;
import com.zpz.framework.zpzoauth.pojo.qo.ModifyUserLoginDateQo;
import com.zpz.framework.zpzoauth.pojo.vo.UserAuthenticationVo;
import com.zpz.framework.zpzoauth.config.oauth.authorization.exouath.ZpzOauthIntegrationAuthentication;
import com.zpz.framework.zpzoauth.config.oauth.authorization.exouath.authenticator.AbstractPreparableIntegrationAuthenticator;
import com.zpz.framework.zpzoauth.config.oauth.authorization.exouath.authenticator.sms.event.ZpzOauthSmsAuthenticateBeforeEvent;
import com.zpz.framework.zpzoauth.config.oauth.authorization.exouath.authenticator.sms.event.ZpzOauthSmsAuthenticateSuccessEvent;
import com.zpz.framework.zpzoauth.service.ZpzOauthFrameUserService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;


/**
 * @author zhangpanzhi
 * @time 2019-07-09
 * @description 未经本人允许请勿随便改动，尊重劳动
 * */
@Component
public class ZpzOauthSmsIntegrationAuthenticator extends AbstractPreparableIntegrationAuthenticator implements ApplicationEventPublisherAware {
    private Logger log = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private ZpzOauthFrameUserService zpzOauthFrameUserService;
    @Resource
    private FrameDepartmentMapper frameDepartmentMapper;
    @Resource
    private ZpzOauthRequestUtil zpzOauthRequestUtil;
    @Autowired
    private PasswordEncoder passwordEncoder;
    private ApplicationEventPublisher applicationEventPublisher;
    private final static String SMS_AUTH_TYPE = "sms";
    public static Integer LOGIN_MODE;
    @Value("${zpzOauth.user.login.mode}")
    public void setLoginMode(Integer loginMode){
        LOGIN_MODE=loginMode;
    }
    @Override
    public UserAuthenticationVo authenticate(ZpzOauthIntegrationAuthentication integrationAuthentication) {
        log.info("手机号+验证码模式登录：入参："+ JSON.toJSONString(integrationAuthentication));
        //获取密码，实际值是验证码
        String password = integrationAuthentication.getAuthParameter("password");
        //获取用户名，实际值是手机号
        String username = integrationAuthentication.getUsername();
        //验证验证码
        boolean b = ZpzOauthMsgUtils.validateMsgCode(username,password);
        if (!b){
            throw new OAuth2Exception("登录授权失败[ZPZ_DEFINED_OAUTH2_EXCEPTION]["+ ZpzOauthResultStatus.OAUTH_10007.getCode() +"]："+ ZpzOauthResultStatus.OAUTH_10007.getMessage());
        }
        //发布事件，可以监听事件进行自动注册用户
        this.applicationEventPublisher.publishEvent(new ZpzOauthSmsAuthenticateBeforeEvent(integrationAuthentication));
        //通过手机号码查询用户
        ZpzOauthResultMsg<UserAuthenticationVo> re=null;
        if (LOGIN_MODE==1||integrationAuthentication.getLoginMode()==1){
           re = zpzOauthFrameUserService.findUserByPhoneNumberCodeLogin(username,integrationAuthentication.getClientId(),integrationAuthentication.getSource());
        }else {
            re = zpzOauthFrameUserService.findUserByPhoneNumber(username,integrationAuthentication.getClientId());
        }
        log.info("手机号+验证码模式登录：查询用户结果："+JSON.toJSONString(re));
        if (re != null&&re.getData()!=null&&re.getCode()==0) {
            UserAuthenticationVo data = re.getData();
            OauthClientDetails client = zpzOauthRequestUtil.getClient(integrationAuthentication.getClientId());
            if (client.getAccessType()==2){
                // 基于部门的权限划分部门禁用或者冻结旗下用户同样不能登录
                List<GetDepartmentStatusPe> getDepartmentStatusPes = frameDepartmentMapper.selectDepartmentStatus(data.getUserCode());
                for (GetDepartmentStatusPe gdsp:getDepartmentStatusPes) {
                    if (gdsp.getStatus()!=0){
                        data.setStatus(-1);
                        break;
                    }
                }
            }
            if (LOGIN_MODE!=null&&LOGIN_MODE==1&&data.getRegisterStatus()!=null&&data.getRegisterStatus()==1){
                data.setRegisterStatus(1);
            }else{
                data.setRegisterStatus(0);
            }
            if (!data.getType().contains(integrationAuthentication.getClientId())){
                throw new OAuth2Exception("登录授权失败[ZPZ_DEFINED_OAUTH2_EXCEPTION]["+ ZpzOauthResultStatus.OAUTH_10008.getCode() +"]："+ ZpzOauthResultStatus.OAUTH_10008.getMessage()+"：：："+re.getMessage());
            }
            if (data.getStatus().intValue()!= ZpzOauthCommonConstant.USER_STATUS_ENABLED.intValue()){
                throw new OAuth2Exception("登录授权失败[ZPZ_DEFINED_OAUTH2_EXCEPTION]["+ ZpzOauthResultStatus.OAUTH_10009.getCode() +"]："+ ZpzOauthResultStatus.OAUTH_10009.getMessage()+"：：："+re.getMessage());
            }
            if (StringUtils.isNotBlank(data.getLockType())&&data.getLockType().contains(integrationAuthentication.getClientId())){
                throw new OAuth2Exception("登录授权失败[ZPZ_DEFINED_OAUTH2_EXCEPTION]["+ ZpzOauthResultStatus.OAUTH_10010.getCode() +"]："+ ZpzOauthResultStatus.OAUTH_10010.getMessage()+"：：："+re.getMessage());
            }
            //将密码设置为验证码
            data.setPassword(passwordEncoder.encode(password));
            //发布事件，可以监听事件进行消息通知
            this.applicationEventPublisher.publishEvent(new ZpzOauthSmsAuthenticateSuccessEvent(integrationAuthentication));
            //将手机号赋值给usernanme
            data.setUserName(username);
            ModifyUserLoginDateQo t=new ModifyUserLoginDateQo();
            t.setUserCode(data.getUserCode());
            t.setClientId(integrationAuthentication.getClientId());
            t.setLoginDate(new Date());
            ZpzOauthResultMsg<Boolean> flag = zpzOauthFrameUserService.modifyUserLoginDate(t);
            log.info("::::::::::修改最新登录时间："+JSON.toJSONString(flag));
            return data;
        }else{
            throw new OAuth2Exception("登录授权失败[ZPZ_DEFINED_OAUTH2_EXCEPTION]["+ ZpzOauthResultStatus.OAUTH_10006.getCode() +"]："+ ZpzOauthResultStatus.OAUTH_10006.getMessage()+"：：："+re.getMessage());
        }
    }

    @Override
    public void prepare(ZpzOauthIntegrationAuthentication integrationAuthentication) {
//        String smsToken = integrationAuthentication.getAuthParameter("sms_token");
//        String smsCode = integrationAuthentication.getAuthParameter("password");
//        String username = integrationAuthentication.getAuthParameter("username");
//        ValidationSmsQo vs = new ValidationSmsQo();
//        vs.setPhone(username);
//        vs.setValidateContent(smsCode);
//        ResultMsg<Boolean> re = msgService.validationSms(vs);
//        if (re==null||re.getCode()!=0||!re.getData()){
//            throw new OAuth2Exception("验证码错误或已过期");
//        }
    }

    @Override
    public boolean support(ZpzOauthIntegrationAuthentication integrationAuthentication) {
        return SMS_AUTH_TYPE.equals(integrationAuthentication.getAuthType());
    }

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.applicationEventPublisher = applicationEventPublisher;
    }
}

